/*
 *  encastrepenalty.cpp
 *  EPPI-0.0
 *
 *  Created by Juan Carlos Garcia Orden on 19/05/2011
 *
 */

#include "encastrepenalty.h"

EncastrePenalty::EncastrePenalty(ifstream &in, string cname, MecSystem *pSys)
:	Joint(in,cname,pSys),
	endTime(0.0)
{	
	dim = parentSystem->dim;	/** Must be set always.  dim belongs to the mother class Body */
	
	char keyword[20];
	string auxs;			/** Aux string */
	vector<string> auxsv(1);	/** Aux string vector */
	int numPoints;
	int i;
	vector<string>	vBodyNames;
	string fixedofs = "all";
	string line;
	stringstream stnum;
	double pen = -999.0;
	
	while (in >> keyword && strcmp(keyword,"ENDJOINT") ) 
	{
	  	if(!strcmp(keyword,"DOFS"))
		{
		  in >> fixedofs;
		}
		if(!strcmp(keyword,"PENALTY"))
		{
			in >> pen;
		}
		if(!strcmp(keyword,"ENDTIME"))
		{
			in >> endTime;
		}				
//		if(!strcmp(keyword,"BODY"))
		if(!strcmp(keyword,"POINTS"))
		{
			// keyword has the BODY label
//			in >> auxs;					/** Reads the name of the body */
//			vBodyNames.push_back(auxs);
			/** Extract the system name where the body is */
//			string sysName = getStringHead(auxs);	

//			in >> auxs;					/** Reads keyword POINTS */
			
			getline(in,line);
			//cout << "line is " << line << "\n";
			istringstream iss(line);
			while (iss >> keyword )
			{
				auxs = keyword;
				//cout << "keyword is " << keyword << endl;
				if(checkForSlash(auxs)==false && !(parentSystem->pointNames).count(auxs))	// belongs to this system because does not have slash and it is in the point list
				{
					addSystemName(auxs,parentSystem->name);
				}
				auxsv[0] = auxs;
				
				if (!fixedofs.compare("123"))
				{
					if (pen!=-999.0)
					{
						vConstraints.push_back(new Fix(auxsv,1,dim,endTime,pen));
						vConstraints.push_back(new Fix(auxsv,2,dim,endTime,pen));
						vConstraints.push_back(new Fix(auxsv,3,dim,endTime,pen));
					}
					else 
					{
						vConstraints.push_back(new Fix(auxsv,1,dim,endTime));
						vConstraints.push_back(new Fix(auxsv,2,dim,endTime));
						vConstraints.push_back(new Fix(auxsv,3,dim,endTime));						
					}
				}
				else if(!fixedofs.compare("12"))
				{
					if (pen!=-999.0)
					{
						vConstraints.push_back(new Fix(auxsv,1,dim,endTime,pen));
						vConstraints.push_back(new Fix(auxsv,2,dim,endTime,pen));
					}
					else 
					{
						vConstraints.push_back(new Fix(auxsv,1,dim,endTime));
						vConstraints.push_back(new Fix(auxsv,2,dim,endTime));
					}
				}
				else if(!fixedofs.compare("13"))
				{
					if (pen!=-999.0)
					{
						vConstraints.push_back(new Fix(auxsv,1,dim,endTime,pen));
						vConstraints.push_back(new Fix(auxsv,3,dim,endTime,pen));						
					}
					else 
					{
						vConstraints.push_back(new Fix(auxsv,1,dim,endTime));
						vConstraints.push_back(new Fix(auxsv,3,dim,endTime));						
					}
				}
				else if(!fixedofs.compare("23"))
				{
					if (pen!=-999.0)
					{
						vConstraints.push_back(new Fix(auxsv,2,dim,endTime,pen));
						vConstraints.push_back(new Fix(auxsv,3,dim,endTime,pen));		
					}
					else 
					{
						vConstraints.push_back(new Fix(auxsv,2,dim,endTime));
						vConstraints.push_back(new Fix(auxsv,3,dim,endTime));		
					}
				}
				else if(!fixedofs.compare("1") )
				{
					if (pen!=-999.0)
					{
						vConstraints.push_back(new Fix(auxsv,1,dim,endTime,pen));
					}
					else
					{
						vConstraints.push_back(new Fix(auxsv,1,dim,endTime));
					}
				}
				else if(!fixedofs.compare("2"))
				{
					if (pen!=-999.0)
					{
						vConstraints.push_back(new Fix(auxsv,2,dim,endTime,pen));
					}
					else 
					{
						vConstraints.push_back(new Fix(auxsv,2,dim,endTime));
					}
				}
				else if(!fixedofs.compare("3"))
				{
					if (pen!=-999.0)
					{
						vConstraints.push_back(new Fix(auxsv,3,dim,endTime,pen));
					}
					else 
					{
						vConstraints.push_back(new Fix(auxsv,3,dim,endTime));					
					}
				}
				else if(!fixedofs.compare("all"))
				{
					// WARNING: At this point I do not know the number of dofs of the point
					// so I just guess that they will be 3
					if (pen!=-999.0)
					{
						vConstraints.push_back(new Fix(auxsv,1,dim,endTime,pen));
						vConstraints.push_back(new Fix(auxsv,2,dim,endTime,pen));
						vConstraints.push_back(new Fix(auxsv,3,dim,endTime,pen));				
					}
					else 
					{
						vConstraints.push_back(new Fix(auxsv,1,dim,endTime));
						vConstraints.push_back(new Fix(auxsv,2,dim,endTime));
						vConstraints.push_back(new Fix(auxsv,3,dim,endTime));				
					}
				}
			}
		} else if(!strcmp(keyword,"POINTSET"))
		{
			in >> auxs;					/** Reads the name of the set of points */
			if(checkForSlash(auxs)==false)	addSystemName(auxs,parentSystem->name);
			for(i=0; i<parentSystem->pointSets[auxs].size(); ++i)
			{
				auxsv[0] = parentSystem->pointSets[auxs][i];
				if (!fixedofs.compare("123"))
				{
					vConstraints.push_back(new Fix(auxsv,1,dim,endTime));
					vConstraints.push_back(new Fix(auxsv,2,dim,endTime));
					vConstraints.push_back(new Fix(auxsv,3,dim,endTime));
				}
				else if(!fixedofs.compare("12"))
				{
					vConstraints.push_back(new Fix(auxsv,1,dim,endTime));
					vConstraints.push_back(new Fix(auxsv,2,dim,endTime));
				}
				else if(!fixedofs.compare("13"))
				{
					vConstraints.push_back(new Fix(auxsv,1,dim,endTime));
					vConstraints.push_back(new Fix(auxsv,3,dim,endTime));						
				}
				else if(!fixedofs.compare("23"))
				{
					vConstraints.push_back(new Fix(auxsv,2,dim,endTime));
					vConstraints.push_back(new Fix(auxsv,3,dim,endTime));		
				}
				else if(!fixedofs.compare("1") )
				{
					vConstraints.push_back(new Fix(auxsv,1,dim,endTime));
				}
				else if(!fixedofs.compare("2"))
				{
					vConstraints.push_back(new Fix(auxsv,2,dim,endTime));
				}
				else if(!fixedofs.compare("3"))
				{
					vConstraints.push_back(new Fix(auxsv,3,dim,endTime));
				}
				else if(!fixedofs.compare("all"))
				{
					// WARNING: At this point I do not know the number of dofs of the point
					// so I just guess that they will be 3
					vConstraints.push_back(new Fix(auxsv,1,dim,endTime));
					vConstraints.push_back(new Fix(auxsv,2,dim,endTime));
					vConstraints.push_back(new Fix(auxsv,3,dim,endTime));				
				}				
//				vComponents.push_back(new Fix(auxsv,fixedofs,dim,endTime));
			}
		}
	}
	if(parentSystem->getProcNum()==parentSystem->getRankNum() ) cout << "	Joint " << name << " succesfully read \n";
}

// ***
/*
void EncastrePenalty::setPTPointsComp()
{
	int j, k;
	vector<string> auxs;
	map<string, Point*, less<string> > maux;
	pair<string,Point*> mauxEntry;
	pair<string,int> sharedEntry;
	
	for(j=0; j<vComponents.size(); j++)		
	//Loop on the components
	{
		auxs = (vComponents[j]->getPointNames());
		for(k=0; k<auxs.size(); k++)		
		// Loop on the names of the points within each component
		{
			// If the point it is not at the local process ...
			if( (parentSystem->checkIfPointProcess(auxs[k]))==false )
			{
				// ...  create it at root system, copying the original point from the remote process
				parentSystem->createPointAtRoot( parentSystem->getPTPoint(auxs[k]) );
				// ...  and add the name of the shared point at the remote process
//				cout << "Nombre del sistema = " << parentSystem->name << endl;
//				cout << "en el proceso = " << parentSystem->getProcNum() << endl;
//				cout << "Nombre del punto = " << auxs[k] << endl;
				parentSystem->addRemoteSharedPoint(auxs[k],parentSystem->getProcNum());
			}
			mauxEntry.first = auxs[k];
			mauxEntry.second = (parentSystem->getPTPointLocal(auxs[k]));
			maux.insert(mauxEntry);
		}
		vComponents[j]->setMPoints(maux);
		maux.clear();
	}
}

// ***

void EncastrePenalty::setPTPointsLoad()
{
	int j, k;
	vector<string> auxs;
	map<string, Point*, less<string> > maux;
	pair<string,Point*> mauxEntry;
	pair<string,int> sharedEntry;
	
	for(j=0; j<vLoads.size(); j++)		
	//Loop on the Loads
	{
		auxs = (vLoads[j]->getPointNames());
		for(k=0; k<auxs.size(); k++)		
		// Loop on the names of the points within each component
		{
			// If the point it is not at the local process ...
			if( (parentSystem->checkIfPointProcess(auxs[k]))==false )
			{
				// ...  create it at root system, copying the original point from the remote process
				parentSystem->createPointAtRoot( parentSystem->getPTPoint(auxs[k]) );
				// ...  and add the name of the shared point at the remote process
				parentSystem->addRemoteSharedPoint(auxs[k],parentSystem->getProcNum());
			}
			mauxEntry.first = auxs[k];
			mauxEntry.second = (parentSystem->getPTPointLocal(auxs[k]));
			maux.insert(mauxEntry);
		}
		vLoads[j]->setMPoints(maux);
		maux.clear();
	}

}
*/
// ***

void EncastrePenalty::setPTPointsCons()
{
	int j, k;
	vector<string> auxs;
	map<string, Point*, less<string> > maux;
	pair<string,Point*> mauxEntry;
	pair<string,int> sharedEntry;
	
	for(j=0; j<vConstraints.size(); j++)		
	{
		auxs = (vConstraints[j]->getPointNames());
		for(k=0; k<auxs.size(); k++)		
			// Loop on the names of the points within each component
		{
			// If the point it is not at the local process ...
			if( (parentSystem->checkIfPointProcess(auxs[k]))==false )
			{
				// ...  create it at root system, copying the original point from the remote process
				parentSystem->createPointAtRoot( parentSystem->getPTPoint(auxs[k]) );
				// ...  and add the name of the shared point at the remote process
				parentSystem->addRemoteSharedPoint(auxs[k],parentSystem->getProcNum());
			}
			mauxEntry.first = auxs[k];
			mauxEntry.second = (parentSystem->getPTPointLocal(auxs[k]));
			maux.insert(mauxEntry);
		}
		vConstraints[j]->setMPoints(maux);
		maux.clear();
	}		
}

// ***
/*
void EncastrePenalty::setPTPoints()
{
	int i;
	for(i=0;i<vPointNames.size();i++)
	{
		vPoints.push_back( parentSystem->getPTPointLocal(vPointNames[i]) );
	}
}
*/
// ***
/*
void EncastrePenalty::setPTBodies()
{}
*/
// ***

void EncastrePenalty::setPPointSurface()
{}

// ***
/*
void EncastrePenalty::writeFileGraph(ofstream &fGraph, string& gFormat)
{}
*/
// ***

void EncastrePenalty::writeMSH(ofstream &fGraph)
{}

// ***

void EncastrePenalty::writeVTU(ofstream &fGraph)
{
	localFGraph << "<?xml version=\"1.0\"?>\n";
	localFGraph << "<VTKFile type=\"UnstructuredGrid\" version=\"0.1\" byte_order=\"LittleEndian\">\n";
	localFGraph << "	<UnstructuredGrid>\n";
	localFGraph << "		<Piece NumberOfPoints=\"" << 0 << "\" NumberOfCells=\"" << 0 << "\">\n";
	localFGraph << "			<Points>\n";
	localFGraph << "				<DataArray type=\"Float64\" NumberOfComponents=\"3\" format=\"ascii\">";
	localFGraph << "\n";
	localFGraph << "				</DataArray>\n";
	localFGraph << "			</Points>\n";
	localFGraph<< "			<Cells>\n";
	localFGraph << "				<DataArray type=\"Int32\" Name=\"connectivity\" format=\"ascii\">";
	
	localFGraph << "\n";
	localFGraph << "					";
	
	localFGraph << "\n";
	localFGraph << "				</DataArray>\n";
	localFGraph << "				<DataArray type=\"Int32\" Name=\"offsets\" format=\"ascii\">";
	localFGraph << "\n";
	localFGraph << "					";
	
	localFGraph << "\n";
	localFGraph << "				</DataArray>\n";
	localFGraph << "				<DataArray type=\"UInt8\" Name=\"types\" format=\"ascii\">";
	localFGraph << "\n";
	localFGraph << "					";

	localFGraph << "\n";
	localFGraph << "				</DataArray>\n";
	localFGraph<< "			</Cells>\n";
	
	localFGraph << "		</Piece>\n";
	
	localFGraph << "	</UnstructuredGrid>\n";
	localFGraph << "</VTKFile>\n";
}

// ***

void EncastrePenalty::writeOOGL(ofstream &fGraph)
{}

// ***
/*
void EncastrePenalty::writeFileTemp(const double&, ofstream &)
{}
*/
// ***
/*
void EncastrePenalty::setIniPosJoint(vector<double>& iniValues)
{}
*/
